﻿using System;
using System.Collections.Generic;
using HydroDesktop.Database.Tests.MappingTests.MetadataCache;
using log4net;
using NinjaCross.Classes.FireBenchmarks.NUnitAddIn.Core;
using NUnit.Framework;
using HydroDesktop.ObjectModel;
//using NinjaCross.Classes.FireBenchmarks.NUnitAddIn.Core;

namespace HydroDesktop.Database.Tests.Performance.MetadataCachePerformanceTests
{
    [TestFixture]
    public class MetadataCachePerformanceTest
    {
        static Random random = new Random();
        static ILog perfLog = LogManager.GetLogger("MdCachePerfTest");
        private MetadataCacheManagerSQL manager;

        [SetUp]
        public void SetupManager()
        {
            manager = GetManager(); 
        }

        [Test]
        [Category("SmallTests")]
        [NJC_TestPerformanceRecorder
        (
        OutputTargetFormat = NJC_TestPerformanceTargetFormat.Html, // Xhtml file output
        OutputTargetIdentificationFormat = NJC_TestPerformanceTargetIdentificationFormat.MethodName, // full method name
        OutputTarget = "..\\PerformanceRepository\\MetadataCache", // in real-world code, a constant would be better
        OutputTargetWriteMode = NJC_TestPerformanceTargetWriteMode.Append // append to previous trackings
        )]
        public void Save10Series()
        {
            SaveSeries(10);
        }

        [Test]
        [Category("SmallTests")]
        [NJC_TestPerformanceRecorder
        (
        OutputTargetFormat = NJC_TestPerformanceTargetFormat.Html, // Xhtml file output
        OutputTargetIdentificationFormat = NJC_TestPerformanceTargetIdentificationFormat.MethodName, // full method name
        OutputTarget = "..\\PerformanceRepository\\MetadataCache", // in real-world code, a constant would be better
        OutputTargetWriteMode = NJC_TestPerformanceTargetWriteMode.Append // append to previous trackings
        )]
        public void Save100Series()
        {
            SaveSeries(100);
        }

        [Test]
        [Category("MediumTests")]
        [NJC_TestPerformanceRecorder
        (
        OutputTargetFormat = NJC_TestPerformanceTargetFormat.Html, // Xhtml file output
        OutputTargetIdentificationFormat = NJC_TestPerformanceTargetIdentificationFormat.MethodName, // full method name
        OutputTarget = "..\\PerformanceRepository\\MetadataCache", // in real-world code, a constant would be better
        OutputTargetWriteMode = NJC_TestPerformanceTargetWriteMode.Append // append to previous trackings
        )]
        public void Save2_1000Series()
        {
            SaveSeries(1000);
        }

        [Test]
        [Category("BigTests")]
        [NJC_TestPerformanceRecorder
        (
        OutputTargetFormat = NJC_TestPerformanceTargetFormat.Html, // Xhtml file output
        OutputTargetIdentificationFormat = NJC_TestPerformanceTargetIdentificationFormat.MethodName, // full method name
        OutputTarget = "..\\PerformanceRepository\\MetadataCache", // in real-world code, a constant would be better
        OutputTargetWriteMode = NJC_TestPerformanceTargetWriteMode.Append // append to previous trackings
        )]
        public void Save3_10000Series()
        {
            SaveSeries(10000);
        }
        [TestCase(10)]
        [TestCase(100)]
        // [TestCase(1000)]
        //[TestCase(10000)]
        public void SaveSeries(int runSize)
        {
            int rnd = random.Next(1000);
            DateTime startTime = DateTime.Now;
            DateTime latstTime = startTime;

            perfLog.Info("Starting LoadAndCheckExistingSeries loops:" + runSize);

            DataServiceInfo dataServiceInfo = DataServiceTest.CreateDataService();

            perfLog.Info("Initialize Repository Manager" + (DateTime.Now - latstTime).Milliseconds);
            latstTime = DateTime.Now;
            //a theme is created
           // Theme theme1 = ThemesTest.CreateTheme();


            perfLog.Info("Initialized theme" + (DateTime.Now - latstTime).Milliseconds);
            latstTime = DateTime.Now;

            //a series is created and saved to database

            List<SeriesMetadata> series = new List<SeriesMetadata>(runSize);
            for (int i = 0; i < runSize; i++)
            {
                series.Add(new SeriesMetadata(SeriesTest.CreateSeries(random.Next())));

            }
            perfLog.Info("Created Series" + (DateTime.Now - latstTime).Milliseconds);
            latstTime = DateTime.Now;

            //  manager.BeginTransaction();
            foreach (SeriesMetadata s in series)
            {
                manager.SaveSeries(s, dataServiceInfo);

            }
            perfLog.Info("Saved Series" + (DateTime.Now - latstTime).Milliseconds);
            latstTime = DateTime.Now;


            //  manager.Commit();

            ////a new identical series is created in-memory
            //Series series2 = HydroDesktop.Database.Tests.DataSeriesTest.CreateSeries(rnd);
            //series2.Site = series1.Site;
            //series2.Variable = series1.Variable;
            //series2.Method = series1.Method;
            //series2.QualityControlLevel = series1.QualityControlLevel;
            //series2.Source = series1.Source;

            //Series existing = manager.SeriesDAO.CheckForExisting(series2);

            //Assert.AreEqual(series2.Id, 0, "series2 should be unsaved (id==0)");
            //Assert.AreNotEqual(existing.Id, 0, "the 'existing' series should be retrieved from db (id > 0)");

            //the 'existing' series should be equal to 'series1' previously saved
            //Assert.AreEqual(existing, series1, "The 'existing' series should be equal to 'series1' previously saved.");
            foreach (SeriesMetadata s in series)
            {
                manager.SaveSeries(s, dataServiceInfo);
                
            }

            //TODO validate that it work
                //Assert.AreEqual(s.ValueCount, fromDB.ValueCount, "the retrieved series should have no values.");
                //Assert.AreEqual(s.ValueCount, fromDB.ValueCount, "the retrieved series should have no values.");
        
        }

      

        static MetadataCacheManagerSQL GetManager()
        {
            return Config.MetadataCacheManager;
        }

    }
}